{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2a9d7073",
   "metadata": {},
   "source": [
    "# 特征值工程"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55936d73",
   "metadata": {},
   "source": [
    "* 在机器学习中，特征值(feature)是可度量的，反映观察对象特征的度量。特征值一般是数值型的，在特定应用中，结构化的或者图形化的特征值在模式识别中也有广泛的应用。当一个观察对象具有多维的特征时，特征值就构成了一个特征向量(feature vector)。所有观察对象的特征向量构成的空间就是特征空间(feature space)。\n",
    "\n",
    "* **特征值的重要性在于，它的选取和构造直接影响了模型的性能。\n",
    "    原始数据的选取，特征值的构造和选择组成了特征值工程的主要部分**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3bc234c0",
   "metadata": {},
   "source": [
    "### 从原始数据抽取特征值的缺陷：\n",
    "\n",
    "*含有冗余信息，数据量过大，信息缺失，信息没有数字化，等等。*"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d458995",
   "metadata": {},
   "source": [
    "### 因此需要对原始数据进行处理：\n",
    " * 标准化 (Standardization)：对所有样本的某个特征值缩放成平均值为0，标准方差为1的状态，即：\n",
    "    **[xi - mean(x)] / std(xi)**  \n",
    " \n",
    " *  归一化 (Normalization)：对所有样本的某个特征值缩放成0和1之间，即：\n",
    "    **[xi - min(xi)] / [max(xi) - min(xi)]**\n",
    "\n",
    "标准化和归一化使得特征值之间有可比性，避免绝对值大的特征值起决定型的作用，从而提高模型的精度。同时，最优解的求解过程变得平缓，提高模型的收敛速度。需要注意的是，标准化和归一化的使用要视情况而定。一般来说，标准化更好地保持了样本间距，而归一化更符合统计规律。这两种方法的具体使用需要考虑具体的机器学习模型类型。 \n",
    "\n",
    " * 二值化 (Binarization)：设定一个阈值，并将某一列特征值和阈值相比较，大于阈值的设为1，小于阈值的设为0。二值化的一个例子，是将特征值缺失的信息用0填补，其他的非空信息用1填补。\n",
    "\n",
    "二值化在图像处理中有广泛的应用。图像灰度的值介于0到255之间。二值化将图像上的像素点的灰度值设置为0或255，也即黑或者白。图像的二值化使图像中数据量大为减少，从而能凸显出目标的轮廓。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ac4f363",
   "metadata": {},
   "source": [
    "### 还需要对原始数据进行缺失数据处理 (Imputation)：\n",
    "原始数据中存在数据缺失，通常以空格或者nan标识。\n",
    " * 忽略含有缺失数据的行：适用于行内有多个特征值的缺失，或者类别标签缺失。\n",
    " * 用相关值替换：例如，用同一类特征值的其他非空值的平均值替换。\n",
    " * 用全局常量替换：将缺失的属性值用同一个常数替换。\n",
    " * 基于统计方法的替换：利用回归或者贝叶斯方法等基于推理的工具或决策树归纳确定替换的值。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60d14b42",
   "metadata": {},
   "source": [
    "## 特征编码：将非数值型的特征值转化为数值型：\n",
    " * 忽略含有非数值型特征值的特征：适用于特征值没有包括有用信息。 \n",
    " * 标签编码(label encoding)：当某一非数值的特征取值为有序的离散值，对每一种非数值型值赋予数值代码。\n",
    " * 独热编码(one-hot encoding)：对于无序的非数值型特征，最便捷的编码就是独热编码，即增加新的特征值用以标识原来特征值。例子：原来的特征有两种可能取值：'男'，或者'女'。独热编码将增加两列新的特征，(1,0)对应于'男'，(0,1)对应于'女'。独热编码扩充了特征值，值得注意的是当原有非数值特征取值过多时，扩充后的特征值空间会变得很大。 \n",
    " * 计数编码(count encoding)：对特征的每一类值进行统计，以出现的次数作为新的特征值。\n",
    " * 目标编码(target encoding)：以非数值型特征的每一类取值相对应的目标(target, or label)的平均值作为新的特征值。\n",
    " * (CatBoost encoding)：首先对所有样本进行随机排序，然后针对类别型特征中的某个取值，每个样本的该特征转为数值型时都是基于排在该样本之前的类别标签取均值，同时加入了优先级和优先级的权重系数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccccd3f8",
   "metadata": {},
   "source": [
    "## 特征离散化：连续的特征取值很少直接作为模型的输入。\n",
    " * 例如年龄，取值范围是从0到100的连续整数。离散化对年龄分段，并且对每个分段赋予新的特征值。比如，[0,10]岁赋予0，[11,20]岁赋予1，100岁以上赋予10。离散化以后模型会更加稳定，排除了个别干扰数据的影响，降低模型过度拟合的风险。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7a37e4f",
   "metadata": {},
   "source": [
    "## 多项式特征扩展(Polynomial Transform)：利用多项式变换将低维的特征值映射到高维。\n",
    " * 多项式的次数(degree)一般选取2或者3。例子：假设原有两个特征x1,x2。经过维度为2的多项式变换，增加的特征为：x1^2, x2^2, x1*x2。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cc5980d",
   "metadata": {},
   "source": [
    "~~~\n",
    "---------------------------------------------------------------------------------------------\n",
    "~~~"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "918a6884",
   "metadata": {},
   "source": [
    "# 构造新的特征值 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1476f10",
   "metadata": {},
   "source": [
    "从已有的数据和特征值构造新的特征值。\n",
    "\n",
    "特征相关系数：特征值的相关系数反映了冗余信息。当两个特征的相关系数接近1.0时，其中一个特征可以被移除。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb249b18",
   "metadata": {},
   "source": [
    "* 特征交叉 (Feature Interaction)：组合非数值型特征的离散值，例如，给定两个非数值型特征A和B，A的值是CA，B的值是Music。两个值的组合CA_Music可以作为一个新的特征值。一般来说，在组合新的特征时，需要对原有特征的所有非数值型值进行配对。 \n",
    "* 特征组合 （Feature Cross）：新的特征值是两个或多个原有特征的值的乘积(crossing)，将原有的地位空间的特征值映射到高维空间，在原有的特征空间不能用超平面(hyper-plane)分割边界的特征向量，在提升了维度以后，在高维空间可以更容易地用超平面分割。参见 Support Vector Machines。\n",
    "* 特征变换 （Feature Transform）：在许多统计分析中要求数据具有正态分布。当原有的特征值不服从正态分布时，平方根变换(squared root)或者对数(logrithm)变换使得变换以后的数据更接近于正态分布。 \n",
    "* PCA/ICA：是两种通过变换原有特征值从而减少特征数量，减低维度的方法。变换后的特征含有较少的冗余度，比原来的特征提供更有价值的信息。这种方法主要用于简化模型，降低过度拟合的风险。（PCA: principal component analysis; ICA: Independent component analysis.） \n",
    "#### PCA 的原理请参考：https://blog.codinglabs.org/articles/pca-tutorial.html\n",
    "#### ICA 的原理以及与 PCA 的区别请参考：https://www.cntofu.com/book/85/ml/clean-feature/ica.md/ \n",
    "* K-means 特征聚类（clustering）：应用聚类的方法构造新的特征，原理是对无标签的特征值（作为众多特征值的其中一列）作聚类分析，用聚类分析的标签作为一列新的特征值。K-means是流行的聚类模型，常用于特征值聚类。增加了新的聚类特征值以后，模型性能是否提高依赖于实际问题。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70e800c6",
   "metadata": {},
   "source": [
    "~~~\n",
    "---------------------------------------------------------------------------------------------\n",
    "~~~"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f28ef886",
   "metadata": {},
   "source": [
    "# 特征值选择 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ecfeb868",
   "metadata": {},
   "source": [
    "* Variance feature selection：\n",
    "    当一个特征值的 variance 小于设定的阈值时，我们认为这个特征值没有提供有价值的信息，因而可以剔除。具体的实现中，可以直接计算特征值的 variance，或者调用 scikit 的软件包 "
   ]
  },
  {
   "cell_type": "raw",
   "id": "2071159d",
   "metadata": {},
   "source": [
    ">>> from sklearn.feature_selection import VarianceThreshold "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44eb0e8f",
   "metadata": {},
   "source": [
    "* Univariate feature selection：\n",
    "    基于 univariate statistical test 统计分析的特征选择方法。univariate stattistical test 包含一大类统计方法，其工作原理是根据统计分析返回的 score, p-values 来分析相关随机变量的关联性（即特征值和目标值之间的关联性），从而根据设定的目标选择相应数目的特征值。 以 scikit 为例，特征值的选择有以下几种方法：SelectKBest, SelectPercentile, SelectFpr, SelectFdr, SelectFwe, GenericUnivariateSelect 。每一种方法在调用的时候和 transform 结合使用，以 SelectKBest 为例，返回两个选定的特征值："
   ]
  },
  {
   "cell_type": "raw",
   "id": "7af19f22",
   "metadata": {},
   "source": [
    ">>> from sklearn.datasets import load_iris\n",
    ">>> from sklearn.feature_selection import SelectKBest\n",
    ">>> from sklearn.feature_selection import chi2\n",
    "\n",
    ">>> X, y = load_iris(return_X_y=True)\n",
    "\n",
    ">>> X_new = SelectKBest(chi2, k=2).fit_transform(X, y) "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9057a0fb",
   "metadata": {},
   "source": [
    "* L1 regularization：\n",
    "    普通的线性模型加上带 L1 范数的惩罚函数 (penalty function) 以后，返回的参数往往是稀疏的，即，多数系数都是0。在回归模型中，典型的例子是 Lasso Regression； 在分类模型中，典型的例子是 Logistic Regression， Linear SVC。这样的模型也可以应用于特征值的将维处理。\n",
    "\n",
    "下面的例子中，scikit 的函数 SelectFromModel 和 LinearSVC 结合，用来对特征值矩阵 X 进行降维处理。 "
   ]
  },
  {
   "cell_type": "raw",
   "id": "fd7e2f1c",
   "metadata": {},
   "source": [
    ">>> from sklearn.svm import LinearSVC\n",
    ">>> from sklearn.datasets import load_iris\n",
    ">>> from sklearn.feature_selection import SelectFromModel\n",
    "\n",
    ">>> X, y = load_iris(return_X_y=True)\n",
    "\n",
    ">>> lsvc = LinearSVC(C=0.01, penalty=\"l1\", dual=False).fit(X, y)\n",
    "\n",
    ">>> model = SelectFromModel(lsvc, prefit=True)\n",
    ">>> X_new = model.transform(X) "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "deep",
   "language": "python",
   "name": "deep"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
